package com.lowca.news.service.impl;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import static org.springframework.security.web.context.HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.lowca.news.dao.RoleDao;
import com.lowca.news.dao.UserDao;
import com.lowca.news.dao.support.Pager;
import com.lowca.news.entity.Role;
import com.lowca.news.entity.User;
import com.lowca.news.exception.account.AutoLoginException;
import com.lowca.news.exception.account.EmailExistException;
import com.lowca.news.exception.account.UsernameExistException;
import com.lowca.news.service.UserService;
import com.lowca.news.service.support.UserDetailsAdapter;
import com.lowca.news.web.formbean.AdminUserConditionForm;

import static com.lowca.news.constant.Constants.RoleMeta;

@Service("userService")
public class UserServiceImpl implements UserService {

	private static final Log log = LogFactory.getLog(UserServiceImpl.class);

	@Resource
	private UserDao userDao;
	@Resource
	private RoleDao roleDao;
	@Resource
	private AuthenticationManager authenticationManager;

	private static final Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();

	@Override
	public boolean existUserByUsername(String username) {
		Assert.hasText(username, "username can not be empty");
		return userDao.existByProperty("username", username);
	}

	@Override
	public boolean existUserByEmail(String email) {
		Assert.hasText(email, "email can not be empty");
		return userDao.existByProperty("email", email);
	}

	@Override
	public User getUserByUsername(String username) {
		Assert.hasText(username, "username can not be empty");
		return userDao.findByUsername(username);
	}

	@Override
	public void createUser(User user) throws UsernameExistException,
			EmailExistException {
		Assert.notNull(user, "user is required");
		if (userDao.existByUsername(user.getUsername())) {
			throw new UsernameExistException("username is already exist");
		}
		if (userDao.existByEmail(user.getEmail())) {
			throw new EmailExistException("email is already exist");
		}
		// 对密码进行加密
		String saltedPassword = md5PasswordEncoder.encodePassword(
				user.getPassword(), user.getUsername());
		user.setPassword(saltedPassword);
		// 初始化用户角色
		Role role = roleDao.findByName(RoleMeta.USER.getName());
		role.getUsers().add(user);
		user.getRoles().add(role);
		userDao.save(user);
	}

	@Override
	public User getUserById(Long id) {
		return userDao.get(id);
	}

	@Override
	public void update(User user) {
		userDao.update(user);
	}

	@Override
	public void autoLogin(String username, String originalPassword,
			HttpServletRequest request) throws AutoLoginException {
		Assert.hasText(username, "username is required");
		Assert.hasText(originalPassword, "originalPassword is required");
		Assert.notNull(request, "request can not be null");
		try {
			User user = userDao.findByUsername(username);
			UserDetailsAdapter adapter = new UserDetailsAdapter(user);
			// 利用authenticationManager完成自动登录
			UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
					username, originalPassword, adapter.getAuthorities());
			request.getSession();
			token.setDetails(new WebAuthenticationDetails(request));
			Authentication authenticatedUser = authenticationManager
					.authenticate(token);
			SecurityContextHolder.getContext().setAuthentication(
					authenticatedUser);
			request.getSession().setAttribute(SPRING_SECURITY_CONTEXT_KEY,
					SecurityContextHolder.getContext());
			log.info("自动登录系统成功");
		} catch (Exception e) {
			log.error(e);// 记录下这个错误
			throw new AutoLoginException("auto login failed");
		}
	}

	@Override
	public Pager<User> searchUser(AdminUserConditionForm condition, int pageNo,
			int pageSize) {
		return userDao.searchUser(condition, pageNo, pageSize);
	}

}
